home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000 #2
/
Ham Radio 2000 - Volume 2.iso
/
HAMV2
/
MISC
/
DTMFF110
/
PROCINP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-08-05
|
31KB
|
1,105 lines
/*
* Routine for processing the keyboard input.
*
* Copyright (C) 1995 Philip VanBaren
*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <bios.h>
#include "freq.h"
#include "fft.h"
#include "extern.h"
#include "display.h"
int display_peak = 0; /* Flag for displaying the peak information */
int help_mode = 0; /* Flag indicating help mode 0 (off), 1, or 2 */
int dtmf_mode = 0; /* Flag indicating DTMF mode */
int ctcss_mode = 0; /* Flag indicating CTCSS mode */
int log_mode = 0; /* Flag indicating LogFile mode */
int gen_ctcss = CTCSS_MAX; /* generated CTCSS frequency number
* (init to none) */
double err_ctcss;
int bw_mode = 0; /* Flag indicating a Black/White palette */
int freeze = 0; /* Flag indicating a paused display */
float freq_scalefactor = 1.0; /* Scalefactor for increasing the
* horizonal scale */
float freq_base = 0.0; /* Base frequency for the display */
int bin = 0; /* Bin number for cursor display */
int mic_level = 0; /* Storage for mic input mixer level (0-100) */
int ext_level = 0; /* Storage for ext input mixer level (0-100) */
int int_level = 0; /* Storage for int input mixer level (0-100) */
int i; /* general miscelaneous */
FILE *log_file; /* file pointer of the log_file */
void
cleanup_vga( void )
{
/*
* Clean up VGA registers so Borland libraries work again.
*/
outportb( 0x3c4, 2 );
outportb( 0x3c5, 0x0f ); /* Use all bit planes */
}
void
setup_vga( void )
{
/*
* Set up VGA registers for fast graphics display
*/
outportb( 0x3ce, 1 );
outportb( 0x3cf, 0 ); /* Disable set/reset for all planes */
outportb( 0x3ce, 3 );
outportb( 0x3cf, 0 ); /* No rotate, just write data */
outportb( 0x3ce, 4 );
outportb( 0x3cf, 3 ); /* Read from bit plane 3 */
outportb( 0x3ce, 5 );
outportb( 0x3cf, inportb( 0x3cf ) & 0x70 ); /* Read and write direct to
* memory */
outportb( 0x3ce, 8 );
outportb( 0x3cf, 0xff ); /* Allow modification of all bits */
outportb( 0x3c4, 2 );
outportb( 0x3c5, 12 ); /* Use bit planes 2 and 3 */
}
void
draw_threshold_level( int color )
{
int y;
if ( threshold_level < 0 )
threshold_level = 0;
if ( threshold_level > ys )
threshold_level = ys;
y = ( WINDOW_BOTTOM - WINDOW_TOP ) * threshold_level / ys;
y = ( WINDOW_BOTTOM ) - y;
draw_line( WINDOW_LEFT - 1, y, WINDOW_RIGHT + 1, y, color );
}
void
input_text( char *text, int maxlen, int x, int y )
{
/*
* Input a line of text using graphical display at (x,y) Maximum length
* allowed for input is given by maxlen The input begins with the current
* contents of text, so this must be initialized before calling the
* routine.
*/
int c = 0;
int count;
char ach[3];
ach[1] = '_';
ach[2] = 0;
draw_text_left( x, y, text );
count = strlen( text );
x += count * _font_width;
draw_text_left( x, y, "_" );
while ( ( c != 0x0d ) && ( c != 0x0a ) )
{
c = draw_getch( );
if ( ( ( c == 0x08 ) || ( c == 0x7f ) ) && count )
{
count--;
x -= _font_width;
draw_bar( x, y - 1, x + 2 * _font_width, y + _font_height, 0 );
draw_text_left( x, y, "_" );
}
else if ( count < ( maxlen - 1 ) )
{
if ( ( c >= '0' && c <= '9' ) || ( c >= 'A' && c <= 'Z' ) || ( c >= 'a' && c <= 'z' )
|| c == '.' || c == '\\' || c == '/' || c == ':'
|| c == '*' || c == '#' || c == '-' )
{
draw_bar( x, y - 1, x + _font_width, y + _font_height, 0 );
ach[0] = c;
text[count] = c;
draw_text_left( x, y, ach );
count++;
x += _font_width;
}
}
if ( c == 0x1b )
{
count = 0;
break;
}
}
text[count] = 0;
}
void
update_display( void )
{
/* Update the frequency and amplitude information displayed while */
/* the input is frozen. */
char ach[100];
double re, im;
double amp, db;
int bri = BitReversed[bin];
re = fftdata[bri];
im = fftdata[bri + 1];
amp = sqrt( re * re + im * im ) / 32768.0;
if ( amp != 0 )
db = 20 * log10( amp );
else
db = -100;
draw_bar( 0, 21, 160, 71, 0 );
sprintf( ach, " Freq: %7.5g Hz ", ( double ) bin * SampleRate / fftlen );
draw_text_left( 0, 22, ach );
sprintf( ach, " Amp: %7.5g ", amp );
draw_text_left( 0, 34, ach );
sprintf( ach, " %7.5g db ", db );
draw_text_left( 0, 46, ach );
}
void
highlight( int on )
{
/* Turn highlighting of a specified bin on the display on (1) or off (0) */
int pos;
double freq = ( double ) bin * ( double ) SampleRate / fftlen;
if ( logfreq )
pos = floor( log( freq / freq_base ) / log( fftlen / 2 ) * freq_scalefactor * ( double ) ( WINDOW_RIGHT - WINDOW_LEFT ) + 0.5 );
else
pos = floor( ( freq - freq_base ) * ( double ) ( WINDOW_RIGHT - WINDOW_LEFT ) / ( double ) SampleRate * freq_scalefactor * 2.0 + 0.5 );
if ( on )
{
draw_line( WINDOW_LEFT + pos, WINDOW_TOP, WINDOW_LEFT + pos, lasty[pos], DARK_HIGHLIGHT );
draw_line( WINDOW_LEFT + pos, lasty[pos], WINDOW_LEFT + pos, WINDOW_BOTTOM, LIGHT_HIGHLIGHT );
}
else
{
draw_line( WINDOW_LEFT + pos, WINDOW_TOP, WINDOW_LEFT + pos, lasty[pos], 0 );
draw_line( WINDOW_LEFT + pos, lasty[pos], WINDOW_LEFT + pos, WINDOW_BOTTOM, GRAPH_COLOR );
}
}
void
help_freze( void )
{
draw_bar( WINDOW_LEFT - 5, MGY - 40, WINDOW_RIGHT + 5, MGY + _font_height, 0 );
draw_text_centered( MGX, MGY - 12, "Use arrows to move, Shift_arrows, Home & End to move quickly" );
draw_text_centered( MGX, MGY, "Enter to save to disk, Space to continue" );
}
int
process_input( int c, int repetitions )
{
/* Process any keyboard input received by the program */
char ach[50];
int i;
if ( c == 0 )
return ( 0 );
if ( freeze )
highlight( 0 );
if ( c == ' ' ) /* Toggle freeze mode on/off */
{
freeze = !freeze;
if ( freeze )
{
if ( help_mode )
{
help_mode = 0;
update_header( );
}
if ( ( double ) bin < freq_base * fftlen / SampleRate )
bin = ceil( freq_base * fftlen / SampleRate );
if ( ( double ) bin > maxfreq * fftlen / SampleRate )
bin = floor( maxfreq * fftlen / SampleRate );
help_freze( );
update_display( );
}
else
{
draw_bar( 0, 21, 160, 71, 0 );
update_header( );
}
}
if ( dtmf_mode || ctcss_mode )
{
if ( c == PG_UP )
{
draw_threshold_level( 0 );
threshold_level += ys / 50;
draw_threshold_level( TEXT_COLOR );
}
if ( c == PG_DN )
{
draw_threshold_level( 0 );
threshold_level -= ys / 50;
draw_threshold_level( TEXT_COLOR );
}
if ( c == 'G' || c == 'g' )
{
log_mode = !log_mode;
if ( log_mode )
{
log_file = fopen( "dtmf_fft.log", "a" );
if ( log_file == NULL )
log_mode = 0;
}
else
{
fclose( log_file );
}
update_header( );
}
}
if ( ( c == 'D' || c == 'd' ) && !ctcss_mode ) /* Toggle DTMF mode */
{
dtmf_mode = !dtmf_mode;
if ( dtmf_mode )
{
halt_soundcard( );
EndFFT( );
SampleRate = 5000L;
fftlen = 128;
logfreq = 0;
freq_scalefactor = 1.0;
InitializeFFT( fftlen );
compute_window_function( );
/* Flush the buffers */
for ( i = 0; i < fftlen / 2; i++ )
displayval[i] = 0;
for ( i = 0; i < fftlen; i++ )
fftdata[i] = 0;
/* Re-initialize the display */
p_dtmf = 0;
dtmf_nr[0] = 0;
setup_xscale( );
update_header( );
reset_soundcard( );
}
else
{
update_header( );
draw_threshold_level( 0 );
}
}
else if ( ( c == 'T' || c == 't' ) && !dtmf_mode ) /* Toggle CTCSS mode */
{
ctcss_mode = !ctcss_mode;
if ( ctcss_mode )
{
halt_soundcard( );
EndFFT( );
SampleRate = 5000L;
fftlen = 2048;
logfreq = 1;
freq_scalefactor = 1.0;
InitializeFFT( fftlen );
compute_window_function( );
/* Flush the buffers */
for ( i = 0; i < fftlen / 2; i++ )
displayval[i] = 0;
for ( i = 0; i < fftlen; i++ )
fftdata[i] = 0;
p_dtmf = 0;
dtmf_nr[0] = 0;
/* Re-initialize the display */
setup_xscale( );
update_header( );
reset_soundcard( );
}
else
{
update_header( );
draw_threshold_level( 0 );
}
}
else if ( freeze )
{
/* Keys only valid in freeze-display */
if ( ( c == 0x0d ) || ( c == 0x0a ) ) /* <CR> saves the spectrum
* data to a file */
{
char filename[30];
draw_bar( WINDOW_LEFT - 5, MGY - 1, WINDOW_RIGHT + 5, MGY + _font_height, 0 );
draw_text_left( MGX - 156, MGY, "File in which to save this spectrum:" );
filename[0] = 0;
input_text( filename, sizeof( filename ), MGX + 140, MGY );
if ( filename[0] != 0 )
{
clock_t clk;
FILE *fp = fopen( filename, "w" );
if ( fp )
{
for ( i = 0; i < fftlen / 2; i++ )
{
double re, im;
re = fftdata[BitReversed[i]] / 32768.0;
fprintf( fp, "%g\t%g\n", ( double ) i / ( double ) fftlen
* ( double ) SampleRate, re );
}
fclose( fp );
sprintf( ach, "Spectrum data saved in %s", filename );
}
else
sprintf( ach, "Unable to open (%s)", filename );
draw_bar( WINDOW_LEFT - 5, MGY - 1, WINDOW_RIGHT + 5, MGY + _font_height, 0 );
draw_text_centered( MGX, MGY, ach );
clk = clock( );
while ( !draw_getkey( ) && ( ( clock( ) - clk ) < CLOCKS_PER_SEC * 3 ) );
}
draw_bar( WINDOW_LEFT - 5, MGY - 13, WINDOW_RIGHT + 5, MGY + _font_height, 0 );
help_freze( );
}
if ( c == LEFT_ARROW ) /* Move the cursor one bin left */
if ( !( bioskey( 2 ) & 3 ) ) /* if no shift key is pressed */
{
double current;
bin -= repetitions;
if ( bin <= 0 )
{
if ( logfreq )
bin = 1;
else
bin = 0;
}
current = ( double ) bin *( double ) SampleRate / ( double ) fftlen;
if ( current < freq_base )
{
freq_base = current;
/* Re-initialize the display */
setup_xscale( );
}
update_display( );
}
else
{ /* Move the cursor 10 bins left */
double current;
bin -= 10 * repetitions;
if ( bin <= 0 )
{
if ( logfreq )
bin = 1;
else
bin = 0;
}
current = ( double ) bin *( double ) SampleRate / ( double ) fftlen;
if ( current < freq_base )
{
freq_base = current;
/* Re-initialize the display */
setup_xscale( );
}
update_display( );
}
else if ( c == RIGHT_ARROW )/* Move the cursor one bin right */
if ( !( bioskey( 2 ) & 3 ) ) /* if no shift key is pressed */
{
double current;
bin += repetitions;
if ( bin >= fftlen / 2 )
bin = fftlen / 2 - 1;
current = ( double ) bin *( double ) SampleRate / ( double ) fftlen;
if ( current > maxfreq )
{
if ( logfreq )
freq_base = current / exp( log( fftlen / 2 ) / freq_scalefactor );
else
freq_base = current - ( double ) SampleRate / ( freq_scalefactor * 2.0 );
/* Re-initialize the display */
setup_xscale( );
}
update_display( );
}
else
{
double current;
bin += 10 * repetitions;
if ( bin >= fftlen / 2 )
bin = fftlen / 2 - 1;
current = ( double ) bin *( double ) SampleRate / ( double ) fftlen;
if ( current > maxfreq )
{
if ( logfreq )
freq_base = current / exp( log( fftlen / 2 ) / freq_scalefactor );
else
freq_base = current - ( double ) SampleRate / ( freq_scalefactor * 2.0 );
/* Re-initialize the display */
setup_xscale( );
}
update_display( );
}
else if ( c == HOME ) /* Move the cursor to the lowest frequency */
{
if ( logfreq )
bin = 1;
else
bin = 0;
update_display( );
if ( ( logfreq && ( freq_base > ( ( double ) SampleRate / ( double ) fftlen ) ) )
|| ( !logfreq && ( freq_base > 0 ) ) )
{
freq_base = 0;
/* Re-initialize the display */
setup_xscale( );
}
}
else if ( c == END ) /* Move the cursor to the highest frequency */
{
bin = fftlen / 2 - 1;
update_display( );
if ( maxfreq < ( double ) SampleRate / 2 )
{
freq_base = SampleRate / 2;
/* Re-initialize the display */
setup_xscale( );
}
}
}
else if ( !dtmf_mode && !ctcss_mode )
{
/* Keys only valid in non-freeze display */
if ( c == HOME ) /* Move the cursor to the lowest frequency */
{
if ( logfreq && ( freq_base > ( ( double ) SampleRate / ( double ) fftlen ) ) )
{
/* Re-initialize the display */
freq_base = 0;
setup_xscale( );
}
else if ( !logfreq && ( freq_base > 0 ) )
{
/* Re-initialize the display */
freq_base = 0;
setup_xscale( );
}
}
else if ( c == END ) /* Move the cursor to the highest frequency */
{
if ( maxfreq < ( double ) SampleRate / 2 )
{
freq_base = SampleRate / 2;
/* Re-initialize the display */
setup_xscale( );
}
}
else if ( c == 'H' || c == 'h' || c == '?' || c == '/' ) /* Toggle help mode */
{
help_mode++;
if ( help_mode > 2 )
help_mode = 0;
if ( help_mode )
show_help( );
else
update_header( );
}
else if ( c == 'F' || c == 'f' ) /* Change the FFT length */
{
halt_soundcard( );
EndFFT( );
if ( c == 'f' )
{
for ( i = 0; i < repetitions; i++ )
{
fftlen *= 2;
if ( fftlen > MAX_LEN )
fftlen = 8;
}
}
else
{
for ( i = 0; i < repetitions; i++ )
{
fftlen /= 2;
if ( fftlen < 8 )
fftlen = MAX_LEN;
}
}
InitializeFFT( fftlen );
compute_window_function( );
/* Flush the buffers */
for ( i = 0; i < fftlen / 2; i++ )
displayval[i] = 0;
for ( i = 0; i < fftlen; i++ )
fftdata[i] = 0;
/* Re-initialize the display */
setup_xscale( );
if ( help_mode )
show_help( );
else
update_header( );
reset_soundcard( );
}
else if ( c == 'R' || c == 'r' ) /* Change the sampling rate */
{
char in[6];
draw_bar( WINDOW_LEFT - 5, MGY - 1, WINDOW_RIGHT + 5, MGY + _font_height, 0 );
draw_text_left( MGX - 80, MGY, "Sampling rate: " );
in[0] = 0;
input_text( in, sizeof( in ), MGX + 40, MGY );
if ( in[0] != 0 )
{
halt_soundcard( );
SampleRate = atol( in );
if ( SampleRate < 5000L )
SampleRate = 5000L;
if ( SampleRate > 88200L )
SampleRate = 88200L;
reset_soundcard( );
/* Re-initialize the display */
setup_xscale( );
}
if ( help_mode )
show_help( );
else
update_header( );
}
}
/* Keys valid in both freeze and non-freeze mode */
if ( c == 'I' || c == 'i' )
{
char *p, *s;
int valid;
draw_bar( WINDOW_LEFT - 5, MGY - 40, WINDOW_RIGHT + 5, MGY + 8, 0 );
draw_fontcolor( BORDER_COLOR );
draw_text_left( WINDOW_LEFT, MGY - 12, "DTMF number to compose: " );
dtmf_nr[0] = 0;
input_text( dtmf_nr, 64, WINDOW_LEFT, MGY ); /* maximum 64 DTMF
* numbers */
draw_bar( WINDOW_LEFT - 5, MGY - 16, WINDOW_RIGHT + 5, MGY + 8, 0 );
p = s = dtmf_nr;
valid = 0;
while ( *p != 0 )
{
if ( *p >= 'a' && *p <= 'd' )
*p &= ~0x20; /* upper case */
if ( !( *p >= '0' && *p <= '9' ) && !( *p >= 'A' && *p <= 'D' )
&& *p != '*' && *p != '#' )
*p = '-';
else
valid = 1;
if ( valid )
*s++ = *p;
p++;
}
while ( *--s == '-' )
;
*++s = 0;
update_header( );
}
else if ( c == 'A' || c == 'a' )
{
char str[10];
int m = 0;
int err;
int old_ctcss;
draw_bar( 0, 0, 639, 92, 0 );
draw_fontcolor( TEXT_COLOR );
draw_text_centered( ( WINDOW_LEFT + WINDOW_RIGHT ) / 2, 2,
"Arrows to move (\033 \032 \030 \031) / Esc to exit / Enter when done" );
draw_fontcolor( LABEL_COLOR );
draw_text_left( WINDOW_LEFT, 15, "Choose a tone frequency:" );
draw_fontcolor( TEXT_COLOR );
draw_text_left( WINDOW_LEFT + 248, 15, "SPACE toggles" );
draw_fontcolor( GRAPH_COLOR );
draw_text_left( WINDOW_LEFT + 366, 15, "active" );
draw_fontcolor( TEXT_COLOR );
draw_text_left( WINDOW_LEFT + 426, 15, "/" );
draw_fontcolor( BORDER_COLOR );
draw_text_left( WINDOW_LEFT + 440, 15, "inactive" );
old_ctcss = gen_ctcss;
do
{
switch ( m )
{
case ' ':
if ( gen_ctcss < CTCSS_MAX )
if ( gen_ctcss < 32 )
ctcss_act1 ^= 1L << gen_ctcss;
else
ctcss_act2 ^= 1L << ( gen_ctcss - 32 );
break;
case LEFT_ARROW:
if ( gen_ctcss >= 1 )
gen_ctcss--;
break;
case RIGHT_ARROW:
if ( gen_ctcss < CTCSS_MAX )
gen_ctcss++;
break;
case UP_ARROW:
if ( gen_ctcss >= 10 )
gen_ctcss -= 10;
break;
case DOWN_ARROW:
if ( gen_ctcss <= CTCSS_MAX - 10 )
gen_ctcss += 10;
break;
}
for ( i = 0; i <= CTCSS_MAX; i++ )
{
if ( i == CTCSS_MAX )
sprintf( str, "%s", "none" );
else
sprintf( str, "%5.1f", f_ctcss[i] );
if ( i == gen_ctcss )
if ( i < CTCSS_MAX &&
( i < 32 ? ctcss_act1 >> i : ctcss_act2 >> ( i - 32 ) ) & 1 )
draw_fontcolor( TEXT_COLOR );
else
draw_fontcolor( LABEL_COLOR );
else if ( i < CTCSS_MAX &&
( i < 32 ? ctcss_act1 >> i : ctcss_act2 >> ( i - 32 ) ) & 1 )
draw_fontcolor( GRAPH_COLOR );
else
draw_fontcolor( BORDER_COLOR );
draw_text_left( WINDOW_LEFT + ( i % 10 ) * 52, 29 + 11 * ( i / 10 ), str );
}
} while ( ( m = draw_getkey( ) ) != 0x0d && ( m != 0x1b ) );
if ( m == 0x1b )
gen_ctcss = old_ctcss;
else
{
halt_soundcard( );
err_ctcss = generate_CTCSS( gen_ctcss );
reset_soundcard( );
}
draw_bar( 0, 0, 639, 92, 0 );
update_header( );
}
else if ( c == TAB )
{
dtmf_mode = ctcss_mode = 0;
draw_threshold_level( 0 );
update_header( );
if ( dtmf_nr[0] != 0 )
{
draw_fontcolor( TEXT_COLOR );
draw_bar( WINDOW_LEFT - 5, MGY - 16, WINDOW_RIGHT + 5, MGY + _font_height, 0 );
draw_text_left( WINDOW_LEFT, MGY - 12, "Composing: " );
halt_soundcard( );
generate_DTMF( dtmf_nr );
reset_soundcard( );
update_header( );
}
}
else if ( c == UP_ARROW )
{ /* Increase the vertical scale factor */
if ( dtmf_mode || ctcss_mode )
draw_threshold_level( 0 );
{
double last_ys = ys;
for ( i = 0; i < repetitions; i++ )
{
if ( ys > 0.15 )
{
ys -= 0.1;
}
else if ( ys > 0.01 )
{
ys -= 0.01;
if ( ys < 0.01 )
ys = 0.01;
}
}
if ( ys != last_ys )
setup_linscales( );
}
if ( dtmf_mode || ctcss_mode )
draw_threshold_level( TEXT_COLOR );
amplitude_scale( );
}
else if ( c == DOWN_ARROW )
{ /* Decrease the vertical scale factor */
if ( dtmf_mode || ctcss_mode )
draw_threshold_level( 0 );
{
double last_ys = ys;
for ( i = 0; i < repetitions; i++ )
{
if ( ys < 0.095 )
{
ys += 0.01;
}
else if ( ys < 2.00 )
{
ys += 0.1;
if ( ys > 2.0 )
ys = 2.0;
}
}
if ( ys != last_ys )
setup_linscales( );
}
if ( dtmf_mode || ctcss_mode )
draw_threshold_level( TEXT_COLOR );
amplitude_scale( );
}
else if ( ( c == '<' ) || ( c == CTRL_LEFT ) || ( c == ALT_LEFT ) )
{ /* Decrease the horizontal scale factor */
if ( freq_scalefactor > 1.0 )
{
for ( i = 0; ( freq_scalefactor > 1.0 ) && ( i < repetitions ); i++ )
{
freq_scalefactor *= 0.84089641525371; /* 1/(2^0.25) */
if ( logfreq )
freq_base *= exp( log( fftlen / 2 ) * 0.07955179237314 / freq_scalefactor );
else
freq_base -= ( double ) SampleRate *0.03977589618657 / freq_scalefactor;
}
/* Re-initialize the display */
if ( freeze )
{
double current = ( double ) bin * ( double ) SampleRate / ( double ) fftlen;
xrange_check( );
if ( current < freq_base )
{
freq_base = current;
}
if ( current > maxfreq )
{
if ( logfreq )
freq_base = current / exp( log( fftlen / 2 ) / freq_scalefactor );
else
freq_base = current - ( double ) SampleRate / 2.0 / freq_scalefactor;
}
}
setup_xscale( );
}
}
else if ( ( c == '>' ) || ( c == CTRL_RIGHT ) || ( c == ALT_RIGHT ) )
{ /* Increase the horizontal scale factor */
if ( freq_scalefactor < 16.0 )
{
for ( i = 0; ( freq_scalefactor < 16.0 ) && ( i < repetitions ); i++ )
{
if ( logfreq )
freq_base *= exp( log( fftlen / 2 ) * 0.07955179237314 / freq_scalefactor );
else
freq_base += ( double ) SampleRate *0.03977589618657 / freq_scalefactor;
freq_scalefactor *= 1.18920711500272; /* 2^0.25 */
}
/* Re-initialize the display */
if ( freeze )
{
double current = ( double ) bin * ( double ) SampleRate / ( double ) fftlen;
xrange_check( );
if ( current < freq_base )
{
freq_base = current;
}
if ( current > maxfreq )
{
if ( logfreq )
freq_base = current / exp( log( fftlen / 2 ) / freq_scalefactor );
else
freq_base = current - ( double ) SampleRate / 2.0 / freq_scalefactor;
}
}
setup_xscale( );
}
}
else if ( ( c == ',' ) || ( c == LEFT_ARROW ) )
{ /* Shift the horizontal display to the right */
if ( maxfreq < ( double ) SampleRate / 2 )
{
for ( i = 0; ( i < repetitions ) && ( maxfreq < ( double ) SampleRate / 2 ); i++ )
{
if ( logfreq )
freq_base *= exp( log( fftlen / 2 ) / ( 8.0 * freq_scalefactor ) );
else
freq_base += ( double ) SampleRate / ( 16.0 * freq_scalefactor );
xrange_check( );
}
/* Re-initialize the display */
if ( freeze )
{
double current = ( double ) bin * ( double ) SampleRate / ( double ) fftlen;
if ( current < freq_base )
{
bin = ceil( freq_base / ( double ) SampleRate * ( double ) fftlen );
update_display( );
}
}
setup_xscale( );
}
}
else if ( ( c == '.' ) || ( c == RIGHT_ARROW ) )
{ /* Shift the horizontal display to the left */
if ( ( logfreq && ( freq_base > ( ( double ) SampleRate / ( double ) fftlen ) ) )
|| ( !logfreq && ( freq_base > 0 ) ) )
{
for ( i = 0; i < repetitions; i++ )
{
if ( ( logfreq && ( freq_base > ( ( double ) SampleRate / ( double ) fftlen ) ) )
|| ( !logfreq && ( freq_base > 0 ) ) )
{
if ( logfreq )
freq_base /= exp( log( fftlen / 2 ) / ( 8.0 * freq_scalefactor ) );
else
freq_base -= ( double ) SampleRate / ( 16.0 * freq_scalefactor );
}
xrange_check( );
}
/* Re-initialize the display */
if ( freeze )
{
double current = ( double ) bin * ( double ) SampleRate / ( double ) fftlen;
if ( current > maxfreq )
{
bin = floor( maxfreq / ( double ) SampleRate * ( double ) fftlen );
if ( bin >= fftlen / 2 )
bin = fftlen / 2 - 1;
update_display( );
}
}
setup_xscale( );
}
}
else if ( c == 'P' || c == 'p' ) /* Toggle peak display mode on/off */
{
display_peak = !display_peak;
if ( display_peak )
{
draw_text_left( PKX - 64, PKY, "Peak at Hz" );
}
else
{
draw_bar( PKX - 64, PKY - 1, PKX + 79, PKY + _font_height, 0 );
}
}
else if ( c == 'V' || c == 'v' ) /* Redraw the video display */
{
draw_bar( 0, 0, 639, 479, 0 );
/* Refresh the video display */
draw_rectangle( WINDOW_LEFT - 2, WINDOW_TOP - 2, WINDOW_RIGHT + 2, WINDOW_BOTTOM + 2, BORDER_COLOR );
setup_xscale( );
amplitude_scale( );
if ( help_mode )
show_help( );
else
update_header( );
if ( display_peak )
{
draw_text_left( PKX - 64, PKY, "Peak at Hz" );
}
if ( freeze )
{
help_freze( );
update_display( );
}
/* Reset the last-value contents */
for ( i = 0; i < WINDOW_RIGHT - WINDOW_LEFT; i++ )
lasty[i] = WINDOW_BOTTOM;
}
else if ( c == 'S' || c == 's' ) /* Save the current state to an INI
* file */
{
draw_bar( WINDOW_LEFT, MGY - 1, WINDOW_RIGHT + 5, MGY + _font_height, 0 );
draw_text_left( MGX - 130, MGY, "Save the current state to: " );
strncpy( ach, ini_file, 20 );
input_text( ach, 20, MGX + 86, MGY );
if ( ach[0] != 0 )
{
FILE *fp;
strcpy( ini_file, ach );
fp = fopen( ini_file, "w" );
if ( fp )
{
fprintf( fp, "Soundcard: %d\n", Soundcard );
fprintf( fp, "Sample rate: %ld\n", SampleRate );
fprintf( fp, "FFT length: %d\n", fftlen );
fprintf( fp, "Log freq scale: %d\n", logfreq );
fprintf( fp, "Max amp: %g\n", ys );
fprintf( fp, "Base frequency: %g\n", freq_base );
fprintf( fp, "Frequency factor: %g\n", freq_scalefactor );
fprintf( fp, "DTMF & CTCSS threshold level: %g\n", threshold_level );
fprintf( fp, "DTMF delay (100 - 1000 ms): %d\n", 3 * dtmf_delay );
fprintf( fp, "CTCSS active: 0x%08lX, 0x%08lX\n", ctcss_act1, ctcss_act2 );
fprintf( fp, "Background color: %d,%d,%d\n", background.red, background.green, background.blue );
fprintf( fp, "Clipping warning color: %d,%d,%d\n", warn.red, warn.green, warn.blue );
fprintf( fp, "Graph color: %d,%d,%d\n", graph.red, graph.green, graph.blue );
fprintf( fp, "Tick mark color: %d,%d,%d\n", tick.red, tick.green, tick.blue );
fprintf( fp, "Axis label color: %d,%d,%d\n", label.red, label.green, label.blue );
fprintf( fp, "Border color: %d,%d,%d\n", border.red, border.green, border.blue );
fprintf( fp, "Text color: %d,%d,%d\n", text.red, text.green, text.blue );
fprintf( fp, "Cursor upper color: %d,%d,%d\n", darkhl.red, darkhl.green, darkhl.blue );
fprintf( fp, "Cursor lower color: %d,%d,%d\n", lighthl.red, lighthl.green, lighthl.blue );
fclose( fp );
}
else
{
clock_t clk = clock( );
sprintf( ach, "Unable to open %s", ini_file );
draw_bar( WINDOW_LEFT - 5, MGY - 1, WINDOW_RIGHT + 5, MGY + _font_height, 0 );
draw_text_centered( MGX, MGY, ach );
while ( !draw_getkey( ) && ( ( clock( ) - clk ) < 3 * CLOCKS_PER_SEC ) );
}
}
if ( help_mode )
show_help( );
else
update_header( );
if ( freeze )
{
help_freze( );
update_display( );
}
}
else if ( c == 'C' || c == 'c' ) /* Toggle Black/White palette on/off */
{
bw_mode = !bw_mode;
if ( bw_mode )
setbwpalette( );
else
setnormalpalette( );
}
else if ( c == 'L' || c == 'l' ) /* Toggle linear/logarithmic
* frequency axis */
{
/*
* Toggle between linear and logarithmic and equalizer frequency scale
*/
logfreq = !logfreq;
if ( freeze )
{
double current;
if ( logfreq && ( bin == 0 ) )
bin = 1;
current = ( double ) bin *( double ) SampleRate / ( double ) fftlen;
xrange_check( );
if ( current < freq_base )
{
freq_base = current;
}
if ( current > maxfreq )
{
if ( !logfreq )
freq_base = current - ( double ) SampleRate / 2.0 / freq_scalefactor;
else
freq_base = current / exp( log( fftlen / 2 ) / freq_scalefactor );
}
}
setup_xscale( );
}
else if ( mixers )
{
if ( c == '[' ) /* External jack down */
{
ext_level -= 2 * repetitions;
if ( ext_level < 0 )
ext_level = 0;
if ( !help_mode )
{
sprintf( ach, "%3d", ext_level );
draw_bar( LVX + 104, LVY - 1, LVX + 127, LVY + _font_height, 0 );
draw_text_left( LVX + 104, LVY, ach );
}
set_mixer( MIXER_EXT, ext_level );
}
else if ( c == ']' ) /* External jack up */
{
ext_level += 2 * repetitions;
if ( ext_level > 100 )
ext_level = 100;
if ( !help_mode )
{
sprintf( ach, "%3d", ext_level );
draw_bar( LVX + 104, LVY - 1, LVX + 127, LVY + _font_height, 0 );
draw_text_left( LVX + 104, LVY, ach );
}
set_mixer( MIXER_EXT, ext_level );
}
else if ( c == '{' ) /* CD input down */
{
int_level -= 2 * repetitions;
if ( int_level < 0 )
int_level = 0;
if ( !help_mode )
{
sprintf( ach, "%3d", int_level );
draw_bar( LVX + 168, LVY - 1, LVX + 191, LVY + _font_height, 0 );
draw_text_left( LVX + 168, LVY, ach );
}
set_mixer( MIXER_INT, int_level );
}
else if ( c == '}' ) /* CD input up */
{
int_level += 2 * repetitions;
if ( int_level > 100 )
int_level = 100;
if ( !help_mode )
{
sprintf( ach, "%3d", int_level );
draw_bar( LVX + 168, LVY - 1, LVX + 191, LVY + _font_height, 0 );
draw_text_left( LVX + 168, LVY, ach );
}
set_mixer( MIXER_INT, int_level );
}
else if ( c == '(' ) /* Mic input down */
{
mic_level -= 2 * repetitions;
if ( mic_level < 0 )
mic_level = 0;
if ( !help_mode )
{
sprintf( ach, "%3d", mic_level );
draw_bar( LVX + 32, LVY - 1, LVX + 55, LVY + _font_height, 0 );
draw_text_left( LVX + 32, LVY, ach );
}
set_mixer( MIXER_MIC, mic_level );
}
else if ( c == ')' ) /* Mic input up */
{
mic_level += 2 * repetitions;
if ( mic_level > 100 )
mic_level = 100;
if ( !help_mode )
{
sprintf( ach, "%3d", mic_level );
draw_bar( LVX + 32, LVY - 1, LVX + 55, LVY + _font_height, 0 );
draw_text_left( LVX + 32, LVY, ach );
}
set_mixer( MIXER_MIC, mic_level );
}
}
if ( freeze )
highlight( 1 );
return ( c == 'E' || c == 'e' || c == 'Q' || c == 'q' || c == 0x1b );
}